{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# repr\n",
    "\n",
    "源码 `tvm/include/tvm/node/repr_printer.h`"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## `ReprPrinter`\n",
    "\n",
    "```c++\n",
    "/*! \\brief A printer class to print the AST/IR nodes. */\n",
    "class ReprPrinter {\n",
    " public:\n",
    "  /*! \\brief The output stream */\n",
    "  std::ostream& stream;\n",
    "  /*! \\brief The indentation level. */\n",
    "  int indent{0};\n",
    "\n",
    "  explicit ReprPrinter(std::ostream& stream)  // NOLINT(*)\n",
    "      : stream(stream) {}\n",
    "\n",
    "  /*! \\brief The node to be printed. */\n",
    "  TVM_DLL void Print(const ObjectRef& node);\n",
    "  /*! \\brief Print indent to the stream */\n",
    "  TVM_DLL void PrintIndent();\n",
    "  // Allow registration to be printer.\n",
    "  using FType = NodeFunctor<void(const ObjectRef&, ReprPrinter*)>;\n",
    "  TVM_DLL static FType& vtable();\n",
    "};\n",
    "```\n",
    "`ReprPrinter` 打印类，用于打印抽象语法树（AST）或中间表示（IR）节点。它包含以下成员变量和成员函数：\n",
    "\n",
    "1. `std::ostream& stream`：输出流，用于将打印结果输出到指定的流中。\n",
    "2. `int indent{0}`：缩进级别，用于控制打印时的缩进空格数。\n",
    "3. `explicit ReprPrinter(std::ostream& stream)`：构造函数，接收一个输出流参数，并将其赋值给 `stream` 成员变量。\n",
    "4. `TVM_DLL void Print(const ObjectRef& node)`：打印节点的成员函数，接收 `ObjectRef` 类型的参数，表示要打印的节点。\n",
    "5. `TVM_DLL void PrintIndent()`：打印缩进的成员函数，用于在打印节点时添加适当的缩进。\n",
    "6. `using FType = NodeFunctor<void(const ObjectRef&, ReprPrinter*)>`：定义了类型别名 `FType`，表示接受 `ObjectRef` 和 `ReprPrinter*` 参数的函数对象类型。\n",
    "7. `TVM_DLL static FType& vtable()`：静态成员函数，返回 `FType` 类型的引用，用于注册到打印器中。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```c++\n",
    "namespace tvm {\n",
    "namespace runtime {\n",
    "// default print function for all objects\n",
    "// provide in the runtime namespace as this is where objectref originally comes from.\n",
    "inline std::ostream& operator<<(std::ostream& os, const ObjectRef& n) {  // NOLINT(*)\n",
    "  ReprPrinter(os).Print(n);\n",
    "  return os;\n",
    "}\n",
    "}\n",
    "}\n",
    "```\n",
    "这段代码是内联函数，用于重载 `operator<<` 运算符。它接受 `std::ostream` 引用和 `ObjectRef` 常量引用作为参数。函数的作用是将 `ObjectRef` 对象的内容输出到 `std::ostream` 中。\n",
    "\n",
    "在函数内部，首先创建了 `ReprPrinter` 对象，并将 `os` 作为参数传递给它。然后调用 `ReprPrinter` 对象的 `Print` 方法，将 `n` 作为参数传递。最后返回 `os`，以便可以继续使用该流进行其他操作。\n",
    "\n",
    "这个函数通常用于自定义对象的打印输出，使得在调试或日志记录时能够更方便地查看对象的内容。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```c++\n",
    "void ReprPrinter::Print(const ObjectRef& node) {\n",
    "  static const FType& f = vtable();\n",
    "  if (!node.defined()) {\n",
    "    stream << \"(nullptr)\";\n",
    "  } else {\n",
    "    if (f.can_dispatch(node)) {\n",
    "      f(node, this);\n",
    "    } else {\n",
    "      // default value, output type key and addr.\n",
    "      stream << node->GetTypeKey() << \"(\" << node.get() << \")\";\n",
    "    }\n",
    "  }\n",
    "}\n",
    "\n",
    "void ReprPrinter::PrintIndent() {\n",
    "  for (int i = 0; i < indent; ++i) {\n",
    "    stream << ' ';\n",
    "  }\n",
    "}\n",
    "\n",
    "ReprPrinter::FType& ReprPrinter::vtable() {\n",
    "  static FType inst;\n",
    "  return inst;\n",
    "}\n",
    "```\n",
    "这段代码是 C++ 中的类 `ReprPrinter` 的实现。这个类的主要功能是打印对象的内容。\n",
    "\n",
    "1. `Print(const ObjectRef& node)` 函数：这个函数接受 `ObjectRef` 类型的参数 `node`，表示要打印的对象。首先，它获取对象的虚函数表（vtable），然后检查 `node` 是否已定义。如果 `node` 未定义，它将输出 `\"(nullptr)\"`；否则，它将检查虚函数表是否可以调度 `node`。如果可以，它将调用虚函数表对应的函数；否则，它将输出对象的类型键和地址。\n",
    "2. `PrintIndent()` 函数：这个函数用于在打印对象内容时添加缩进。它通过循环输出空格来实现缩进效果。\n",
    "3. `vtable()` 函数：这个函数返回类的静态虚函数表实例。这是一个单例模式的实现，确保在整个程序中只有一个虚函数表实例。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## `Dump`\n",
    "\n",
    "`Dump` 用于将节点信息输出到标准错误流（stderr）以供调试使用。\n",
    "\n",
    "第一个函数的声明如下：\n",
    "```cpp\n",
    "TVM_DLL void Dump(const runtime::ObjectRef& node);\n",
    "```\n",
    "这个函数接受类型为 `runtime::ObjectRef` 的常量引用作为参数，表示输入的节点。函数没有返回值，并且使用了 `TVM_DLL` 宏来指定这是动态链接库中的函数。\n",
    "\n",
    "第二个函数的声明如下：\n",
    "```cpp\n",
    "TVM_DLL void Dump(const runtime::Object* node);\n",
    "```\n",
    "这个函数接受类型为 `runtime::Object` 的常量指针作为参数，表示输入的节点。函数同样没有返回值，并且也使用了 `TVM_DLL` 宏来指定这是动态链接库中的函数。\n",
    "\n",
    "这两个函数的作用是将节点的信息输出到标准错误流，以便开发人员可以查看和调试。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "```c++\n",
    "void Dump(const runtime::ObjectRef& n) { std::cerr << n << \"\\n\"; }\n",
    "\n",
    "void Dump(const runtime::Object* n) { Dump(runtime::GetRef<runtime::ObjectRef>(n)); }\n",
    "\n",
    "TVM_REGISTER_GLOBAL(\"node.AsRepr\").set_body_typed([](runtime::ObjectRef obj) {\n",
    "  std::ostringstream os;\n",
    "  os << obj;\n",
    "  return os.str();\n",
    "});\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "这段代码定义了三个函数，以及全局注册的 TVM 模块。\n",
    "\n",
    "1. `void Dump(const runtime::ObjectRef& n)`：这个函数接受 `runtime::ObjectRef` 类型的参数 `n`，并将其输出到标准错误流（std::cerr）。\n",
    "2. `void Dump(const runtime::Object* n)`：这个函数接受指向 `runtime::Object` 的指针 `n`，然后调用 `Dump` 函数将其转换为 `runtime::ObjectRef` 类型，并输出到标准错误流。\n",
    "\n",
    "3. `TVM_REGISTER_GLOBAL(\"node.AsRepr\")`：这是 TVM 模块的全局注册，用于将名为 `\"node.AsRepr\"` 的函数注册到 TVM 运行时环境中。这个函数接受 `runtime::ObjectRef` 类型的参数，将其转换为字符串，并返回。\n",
    "总结：这段代码定义了用于打印对象引用的函数，以及 TVM 模块的全局注册。"
   ]
  }
 ],
 "metadata": {
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
